package com.qingzhuge.member.utils;
 
import com.aliyuncs.auth.AcsURLEncoder;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.*;

import static com.qingzhuge.common.Constants.DEFAULT_ENCODING;

/**
 * @author : zero.xiao
 * @description : 生成阿里云signNature工具类
 * @date :2018/9/30 0030 下午 17:35
 * @since : 1.0.0
 * @modified :
 */
public class AliyunGenerateSignUtil {
 
	public static String generateSignNature(Map<String, String> map) throws Exception {
		// 1.构建待签名字符串
		// 1.1.按照参数名称的字典顺序对请求中所有的请求参数
		Set<String> keySet = map.keySet();
		List<String> list = new ArrayList<>(keySet);
		List<String> sortList = sort(list);
		// 1.2.对排序之后的请求参数的名称和值分别用UTF-8字符集进行URL编码
		// 1.3.将编码后的参数名称和值用英文等号（=）进行连接
		// 1.4. 将等号连接得到的参数组合按步骤1.1排好的顺序依次使用“&”符号连接，即得到规范化请求字符串
		StringBuilder sb = new StringBuilder();
		for (String key : sortList) {
			//注：这里应该比较low。在测试过程中发现 冒号：最终会被编码会 “%253A”，是经过了两次。有好的方法请告知
			if ("Timestamp".equals(key)) {
				sb.append(AcsURLEncoder.percentEncode(key)).append("=")
						.append(AcsURLEncoder.percentEncode(AcsURLEncoder.percentEncode(map.get(key)))).append("&");
			} else {
				sb.append(AcsURLEncoder.percentEncode(key)).append("=")
						.append(AcsURLEncoder.percentEncode(map.get(key))).append("&");
			}
		}
		String sign = sb.toString();
		String temp = sign.substring(0, sign.length() - 1);
		System.out.println(temp);
		// 1.5.待签名的字符串
		String stringToSign = "POST&" + AcsURLEncoder.percentEncode("/") + "&" + temp.replace("=", "%3D");
		// 2.计算签名
		// 2.1.HMAC值
		byte[] hmacSha1 = hmacsha1(stringToSign, "testsecret&");
		// 2.2.Base64编码
		// 2.3.返回
		return base64encode(hmacSha1);
	}
 
	private static List<String> sort(List<String> list) {
		if (list != null && list.size() > 0) {
			Collections.sort(list);
		}
		return list;
	}
 
	/**
	 * 生成hmacsha1签名
	 * 
	 * @param binaryData
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] hmacsha1(byte[] binaryData, String key) throws Exception {
		Mac mac = Mac.getInstance("HmacSHA1");
		SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
		mac.init(secretKey);
		return mac.doFinal(binaryData);
	}
 
	/**
	 * 生成hmacsha1签名
	 * 
	 * @param plainText
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] hmacsha1(String plainText, String key) throws Exception {
		return hmacsha1(plainText.getBytes(DEFAULT_ENCODING), key);
	}
 
	/**
	 * 生成base64编码
	 * 
	 * @param binaryData
	 * @return
	 */
	public static String base64encode(byte[] binaryData) {
		return Base64.getEncoder().encodeToString(binaryData);
	}
}
